import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.JTextArea;

import weka.core.*;


public class DecisionTreeApplet extends Applet implements ActionListener, ItemListener, Runnable
{
    class MyMouseListener extends MouseAdapter
    {

        public void mousePressed(MouseEvent mouseevent)
        {
            int i = mouseevent.getX();
            int j = mouseevent.getY();
        }

        MyMouseListener()
        {
        }
    }


    public void init()
    {
        super.init();
        super.setSize(1200, 700);
        setLayout(new BorderLayout());
        t_loaddb.add(lbl_database);
        t_loaddb.add(cb_database);
        t_loaddb.add(btn_loaddb);
       
        t_p1.add(lbl_goal);
        t_p1.add(cb_goalAttribute);
        t_p1.add(lbl_learningset);
        t_p1.add(tf_lssize);
        t_p1.add(lbl_lsmode);
        t_p1.add(cb_SelectionChoiceLs);
        cb_SelectionChoiceLs.addItem("First");
        cb_SelectionChoiceLs.addItem("Last");
        cb_SelectionChoiceLs.addItem("Random");

        t_p5.add(sp_listAttributes );
       
        t_p0.add(t_p1);
        top.setLayout(new BorderLayout());
        top.add(t_loaddb, "North");
        top.add(t_p0, "West");
        top.add(t_p5, "Center");

        center.add(tp_show);
        bottom.setLayout(new GridLayout(4, 1, 0, 0));

        t_p1.add(lbl_selectMethod);
        t_p1.add(cb_selectMethod);
        t_p1.add(btn_build = new JButton("Build"));

        bottom.add(b_p2);
        b_p4.add(lbl_testset);
        b_p4.add(tf_tssize);
        b_p4.add(lbl_tsmode);
       
        b_p4.add(cb_SelectionChoiceTs);
        cb_SelectionChoiceTs.addItem("Not in ls");
        cb_SelectionChoiceTs.addItem("Random");
        cb_SelectionChoiceTs.addItem("First");
        cb_SelectionChoiceTs.addItem("Last");
        cb_SelectionChoiceTs.addItem("Learning set");

        b_p4.add(btn_testtree = new JButton("Test tree"));
        b_p4.add(btn_crossvalidation = new JButton("Cross Validation"));
        bottom.add(b_p4);
        add(top, "North");
        add(bottom, "South");

        add(center, "Center");

        if(getParameter("DBFILE") != null)
            try
            {
                initDb("http://www.montefiore.ulg.ac.be/~lwh/Gtdidt/dbs/zoo.db");
            }
            catch(Exception _ex)
            {
                System.out.println("-- database file not found");
                showStatus("Bad url");
            }

        btn_testtree.addActionListener(this);
        btn_crossvalidation.addActionListener(this);
        btn_build.addActionListener(this);
        btn_loaddb.addActionListener(this);

        cb_SelectionChoiceTs.addItemListener(this);
        MyMouseListener mymouselistener = new MyMouseListener();

    }

    public void loadDb()
    {
        try
        {
                db = new Database();
                String url = cb_database.getSelectedItem().toString();    
            initDb(url);                  
            System.out.println("Load database !!!");
           
            //return;
        }
        catch(Exception ex)
        {
            System.out.println("-- database file not found" + ex);
            ex.printStackTrace();
        }
        showStatus("Bad url");
    }

   
    public void initDb(String url)
    {          
        this.tree = null;
        int status=0;
        try{
                status = db.loadDatabase(url);
        }
        catch(Exception e)
        {
                e.printStackTrace();
        }

        showStatus("Loading database");
        System.out.println("Status = " + status);
       
        if(status == 0)
        {
            showStatus("Loading failed : bad file format");
           
            tf_lssize.setText("");
                tf_tssize.setText("");
                cb_SelectionChoiceLs.removeAllItems();
                cb_SelectionChoiceTs.removeAllItems();
                cb_goalAttribute.removeAllItems();
                lst_candatt.removeAll();            
                db = null;
                Message msg = new Message("Fail to load the database");
                msg.show();
            return;
        }
        else
        {


                if(db.data.numAttributes() == 0)
                    System.out.println("no object");
                lst_candatt.removeAll();
                cb_goalAttribute.removeAllItems();
                loadAllAttributesDescription();
                loadGoalAttributesDescription();

                tf_lssize.setText("60");
                tf_tssize.setText("40");
                cb_SelectionChoiceLs.setSelectedIndex(0);
                cb_SelectionChoiceTs.setSelectedIndex(4);

                System.gc();
                showStatus("done");
                setComment("");
        }
    }

    public void loadAllAttributesDescription()
    {
        Vector<String> des = db.getAllAttributesDescription();

        lst_candatt.setListData(des);
    }
   
    public void loadGoalAttributesDescription()
    {
        Vector<String> des = db.getGoalAttributesDescription();
        if(des.size() > 0)
        {
                for(int i=0; i< des.size(); i++)
                {
                        cb_goalAttribute.addItem(des.elementAt(i));
               
                }
                cb_goalAttribute.setSelectedIndex(0);
        }
    }
   
   
    public void NewTree()
    {
        double percent = GetLsSize();        
        int mode = GetLsMode();  
        if(percent == 0)
        {
                percent = 60;
                tf_lssize.setText(""+percent);
        }
       
        if(this.GetGoalAttribute() != null)
                tree = new DecisionTree(db, this.GetCandidateAttributes(), this.GetCandidateAttributesIndex(), this.GetGoalAttribute(), cb_selectMethod.getSelectedIndex(), mode, percent);      
        refreshcurrenttree();
    }
    
    public Vector<Integer> GetCandidateAttributesIndex()
    {
        Vector<Integer> index = new Vector();
        int ai[] = lst_candatt.getSelectedIndices();
       
        for(int i = 0; i < ai.length; i++)
            index.addElement(Integer.valueOf(ai[i]));
        return index;
    }
   
   
    public Vector<Attribute> GetCandidateAttributes()
    {
        Vector<Integer> index = this.GetCandidateAttributesIndex();
        return db.getCandidatAttributes(index);
    }

    public Attribute GetGoalAttribute()
    {          
        if(cb_goalAttribute.getSelectedItem() == null)
                return null;
        String name = cb_goalAttribute.getSelectedItem().toString();
        return db.setGoalAttribute(name);
    }
   

    public double GetLsSize()
    {
        if(tf_lssize.getText().length() == 0)
            return 0;
        else
            return Double.parseDouble(tf_lssize.getText());
    }

    public int GetLsMode()
    {
        return cb_SelectionChoiceLs.getSelectedIndex();
    }

    public double GetTsSize()
    {
        if(tf_lssize.getText().length() == 0)
            return 0;
        else
        {
                System.out.println(" noi dung test set " +tf_tssize.getText().toString());
                return Double.parseDouble(tf_tssize.getText());
        }
           
       
    }

    public int GetTsMode()
    {
        return cb_SelectionChoiceTs.getSelectedIndex();
    }

    public void setComment(String s)
    {
        tf_opennode.setText(s);
    }

    public void start()
    {
        running = true;
        t = new Thread(this);
        t.start();
    }

    public void stop()
    {
        running = false;
    }

    public void run()
    {
    }

    public void ScanAttributes()
    {

        Vector<Integer> index = GetCandidateAttributesIndex();
        Vector<String> scan;

        if(index.size() > 0)
        {
                scan = db.scanCandidatAttributesByIndex(index);
                System.out.println("Scan" + index.size());
                lst_scanAttributes.setListData(scan);          
                tp_show.addTab("Scan Attributes",       lst_scanAttributes);
        }      
    }

    public void prediction()
    {  
        Vector<String> prediction = new Vector();
       
        if(this.db.train!=null)
        {
        	prediction.add("				TRAINING SET");
        	prediction.add("");
            prediction.addAll((Collection)this.tree.prediction(db.train));   
        }
        if(this.db.test!=null)
        {
        	prediction.add("");
        	prediction.add(new String("================================================="));
        	prediction.add("				TEST SET");
        	
        	prediction.addAll((Collection)this.tree.prediction(db.test));
        }
        
        lst_prediction.setListData(prediction);     
        tp_show.remove(sp_prediction);
        sp_prediction = new JScrollPane(lst_prediction);
        tp_show.addTab("Prediction", sp_prediction);       
    }
    public void SplitMore()
    {
        refreshcurrenttree();
    }


    public void changeSelectedNode()
    {
  
    }

    public void buildalltree()
    {
        showStatus("Building the tree...");
        tree.buildTree();

        showStatus("done");
    }

    public void testtree()
    {
        showStatus("Testing the tree...");
        int mode = this.GetTsMode();
        double percent = this.GetTsSize();
       
        if((percent == 0) && (mode >= 1) && (mode <= 3))
        {
                percent = 40;
                tf_tssize.setText(""+percent);
        }
       
        tree.db.setTest(mode, percent);
        String test = tree.testTree();

        tp_show.remove(txt_tabTestTree);
        txt_tabTestTree.setText(test);
        tp_show.addTab("Test Tree", txt_tabTestTree);

        showStatus("done");
    }

    public void CrossValidation()
    {
            showStatus("Cross validation...please wait");
        String crossValidation = tree.crossValidation();

        tp_show.remove(txt_tabCrossValidation);
        txt_tabCrossValidation.setText(crossValidation);
        tp_show.addTab("Cross Validation", txt_tabCrossValidation);
   
        showStatus("done");
    }
    public void actionPerformed(ActionEvent actionevent)
    {
        String s = actionevent.getActionCommand();
       
        if(s == "Scan attributes" && tree != null)
        {
            ScanAttributes();              
            return;
        }

        if(s == "Test tree" && tree != null)
        {
            testtree();
            prediction();
            return;
        }
 
        if((s == "Build" )&& (this.GetCandidateAttributesIndex().size() != 0) && (this.db != null))
        {
            NewTree();
            ScanAttributes();
         
            System.out.println("Prediction");
            return;
        }
        if(s == "Load Database")
        {
               
            loadDb();
            return;
        }
        if(s == "Cross Validation" && tree != null)
        {
            CrossValidation();
            return;
        }

    }

    public void refreshcurrenttree()
    {
    	
    }

    public void itemStateChanged(ItemEvent itemevent)
    {

    }

    public DecisionTreeApplet()
    {

        tf_opennode = new JTextField();
        top = new JPanel();
        lbl_database = new JLabel("Database url : ", 2);

       
        cb_database = new JComboBox(DataInput.dataInputs);
        cb_database.setEditable(true);
       
        btn_loaddb = new JButton("Load Database");
        lbl_goal = new JLabel("Goal Attribute : ", 2);
        lbl_candatt = new JLabel("Candidate attributes : ");
        lbl_learningset = new JLabel("Learning set size:", 2);
        lbl_lssize = new JLabel("size :", 2);
        tf_lssize = new JTextField(5);
        lbl_lsmode = new JLabel("Selection mode:", 2);
        lbl_testset = new JLabel("Test set size :", 2);
        tf_tssize = new JTextField(5);
        lbl_tsmode = new JLabel("Selection mode:", 2);
        t_p0 = new JPanel(new GridLayout(1, 1, 0, 0));
        t_loaddb = new JPanel(new FlowLayout(1, 5, 0));
       
        t_p1 = new JPanel(new GridLayout(5, 2, 0 , 0));
        t_p5 = new JPanel(new GridLayout(1, 1, 0 , 0));
       
        b_p1 = new JPanel(new FlowLayout(1, 5, 0));
        b_p2 = new JPanel(new FlowLayout(1, 5, 0));
        b_p3 = new JPanel(new FlowLayout(1, 5, 0));
        b_p4 = new JPanel(new FlowLayout(1, 5, 0));

        tp_show = new JTabbedPane();
        tp_show.setSize(1200, 400);
       
        cb_goalAttribute = new JComboBox();
        cb_goalAttribute.setAutoscrolls(true);
        cb_goalAttribute.setEditable(false);
        cb_goalAttribute.setVisible(true);
       
        cb_SelectionChoiceTs = new JComboBox();
       
        cb_SelectionChoiceLs = new JComboBox();
       
        lbl_selectMethod = new JLabel("Select method :");
        cb_selectMethod = new JComboBox(Constant.methods);
       
        lbl_tab = new JLabel();
       
        lst_candatt = new JList();
        lst_candatt.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        lst_candatt.setVisibleRowCount(5);
        lst_scanAttributes = new JList();
        lst_prediction = new JList();
       
        sp_listAttributes = new JScrollPane(lst_candatt);
        sp_prediction = new JScrollPane();
        bottom = new JPanel();
       
        center = new JPanel(new BorderLayout());
       
        txt_tabCrossValidation = new JTextArea();
        txt_tabCrossValidation.setEditable(false);
        txt_tabTestTree = new JTextArea();
        txt_tabTestTree.setEditable(false);


    }

    static final int FIXED_FONT_HEIGHT = 10;
    static final int FIXED_FONT_ASCENT = 3;
    double default_scorethres;
    double default_entthres;
    boolean running;
    Thread t;
   
    Database db;
    DecisionTree tree;

    public static JComboBox cb_database;
    public static JComboBox cb_selectMethod;
    public static JComboBox cb_goalAttribute;

    public static JList lst_candatt;
    public static JList lst_scanAttributes;
    public static JList lst_prediction;
   
    public static JLabel lbl_testset;
    public static JLabel lbl_tssize;
    public static JLabel lbl_tab;
    public static JLabel lbl_tsmode;
    public static JLabel lbl_learningset;
    public static JLabel lbl_lssize;
    public static JLabel lbl_lsmode;
    public static JLabel lbl_candatt;
    public static JLabel lbl_selectMethod;
    public static JLabel lbl_goal;
    public static JLabel lbl_database;
   
   
    public static JComboBox cb_SelectionChoiceTs;
    public static JComboBox cb_SelectionChoiceLs;
   
    public static JTextArea txt_tabCrossValidation;
    public static JTextArea txt_tabTestTree;
   
    public static JTextField tf_opennode;
    public static JTextField tf_tssize;
    public static JTextField tf_lssize;
   
    public static JButton btn_testtree;
    public static JButton btn_crossvalidation;
    public static JButton btn_build;
    public static JButton btn_loaddb;
   

    public static JScrollPane sp_listAttributes;
    public static JScrollPane sp_prediction;
   
    public static JPanel t_p0;
    public static JPanel t_loaddb;
    public static JPanel t_p1;
    public static JPanel t_p5;
    public static JPanel b_p1;
    public static JPanel b_p2;
    public static JPanel b_p3;
    public static JPanel b_p4;
    public static JPanel top;
    public static JPanel center;
    public static JPanel bottom;
   
    public static JTabbedPane tp_show;

}

